package org.yunai.swjg.server.module.inventory.item;

import org.slf4j.Logger;
import org.yunai.swjg.server.entity.ItemEntity;
import org.yunai.swjg.server.module.idSequence.IdSequenceHolder;
import org.yunai.swjg.server.module.inventory.container.Bag;
import org.yunai.swjg.server.module.inventory.container.Containable;
import org.yunai.swjg.server.module.inventory.event.ItemCountChangeEvent;
import org.yunai.swjg.server.module.inventory.item.template.ItemTemplate;
import org.yunai.swjg.server.module.player.vo.Player;
import org.yunai.yfserver.common.LoggerFactory;
import org.yunai.yfserver.event.EventDispatcher;
import org.yunai.yfserver.event.IEvent;
import org.yunai.yfserver.persistence.PersistenceObject;
import org.yunai.yfserver.spring.BeanManager;

/**
 * 道具
 * User: yunai
 * Date: 13-4-6
 * Time: 上午11:50
 */
public class Item implements PersistenceObject<Integer, ItemEntity>, Containable {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggerFactory.Logger.item, Item.class);

    private static EventDispatcher eventDispatcher;

    static {
        eventDispatcher = BeanManager.getBean(EventDispatcher.class);
    }

    /**
     * ID
     */
    private Integer id;
    /**
     * 所属玩家
     */
    private Player player;
    /**
     * 佩带着ID
     */
    private Integer ownerId;
    /**
     * 所属背包类型
     */
    private Bag.BagType bagType;
    /**
     * 物品所在背包位置
     */
    private Integer bagIndex;
    /**
     * 道具模版
     */
    private ItemTemplate template;
//    /**
//     * TODO 道具实例属性
//     */
//    private ItemFeature feature;
    /**
     * 叠加数量
     */
    private Integer overlap;
    /**
     * 是否在数据库中
     */
    private boolean inDB;

    private Item() {
    }

    @Override
    public void fromEntity(ItemEntity entity) {
        this.id = entity.getId();
        this.ownerId = entity.getOwnerId();
        this.bagIndex = entity.getBagIndex();
        this.overlap = entity.getOverlap();
        this.bagType = Bag.BagType.valueOf(entity.getBagId());
        this.template = ItemTemplate.getItemTemplate(entity.getTemplateId());
//        if (entity.getProperties() != null && entity.getProperties().length() > 0) {
//            switch (this.template.getIdentityType()) {
//                case EQUIPMENT:
//                    this.feature = JSON.parseObject(entity.getProperties(), EquipFeature.class);
//                    break;
//            }
//        }
    }

    @Override
    public ItemEntity toEntity() {
        ItemEntity entity = new ItemEntity();
        entity.setId(this.id);
        entity.setPlayerId(this.player.getId());
        entity.setOwnerId(this.ownerId);
        entity.setBagIndex(this.bagIndex);
        entity.setOverlap(this.overlap);
        entity.setBagId(this.bagType.getIndex());
        entity.setTemplateId(this.template.getId());
//        switch (this.template.getIdentityType()) {
//            case EQUIPMENT:
//                entity.setProperties(JSON.toJSONString(this.feature));
//                break;
//        }
        return entity;
    }

    @Override
    public Bag.BagType getBagType() {
        return bagType;
    }

    @Override
    public int getIndex() {
        return bagIndex;
    }

//    public void setIndex(int bagIndex) {
//        this.bagIndex = bagIndex;
//    }

    @Override
    public int getOverlap() {
        return overlap;
    }

    @Override
    public int getMaxOverlap() {
        return template.getMaxOverlap();
    }

    public ItemTemplate getTemplate() {
        return template;
    }

    public Integer getTemplateId() {
        return template.getId();
    }

    public ItemDef.Type getType() {
        return template.getType();
    }

    @Override
    public Integer getId() {
        return id;
    }

//    public ItemFeature getFeature() {
//        return feature;
//    }

    /**
     * TODO 很快不用拉
     *
     * @return 是否是空物品
     */
    @Deprecated
    public boolean isEmpty() {
        return getTemplate() == null || getOverlap() == 0;
    }

    @Override
    public boolean isInDB() {
        return inDB;
    }

    @Override
    public void setInDB(boolean inDB) {
        this.inDB = inDB;
    }

    @Override
    public Integer getUnitId() {
        return player.getId();
    }

    /**
     * 提交保存
     */
    public void submitSave() {
        player.getOnline().getDataUpdater().addSave(this);
    }

    /**
     * 提交删除
     */
    public void submitDelete() {
        player.getOnline().getDataUpdater().addDelete(this);
    }

    /**
     * 判断是否是空物品
     *
     * @param item 物品
     * @return 是否是空物品
     */
    public static boolean isEmpty(Item item) {
        return item == null || item.getOverlap() == 0;
    }

    @Override
    public String toString() {
        return "Item{" +
                "id=" + id +
                ", playerEntity=" + player +
                ", ownerId=" + ownerId +
                ", bagType=" + bagType +
                ", bagIndex=" + bagIndex +
                ", template=" + template +
                ", overlap=" + overlap +
                ", inDB=" + inDB +
                '}';
    }

    // ==================== 业务方法BEGIN ====================

    /**
     * 创建道具
     *
     * @param entity 道具实体
     * @param player 玩家
     * @return 道具
     */
    public static Item build(ItemEntity entity, Player player) {
        Item item = new Item();
        item.fromEntity(entity);
        item.player = player;
        item.inDB = true;
        return item;
    }

    /**
     * 保存新道具，并将新道具放入背包，最后返回该道具对象
     *
     * @param player   玩家
     * @param template 道具模版
     * @param bagType  背包类型
     * @param bagIndex 位置
     * @param overlap  道具数量
     * @return 道具对象
     */
    public static Item save(Player player, ItemTemplate template, Bag.BagType bagType,
                            Integer bagIndex, Integer overlap) {
        Item item = new Item();
        item.id = IdSequenceHolder.genItemId();
        item.template = template;
        item.bagType = bagType;
        item.bagIndex = bagIndex;
        item.overlap = 0;
        item.player = player;
        item.inDB = false;
        player.getOnline().getInventory().getBag(bagType).putItem(item);
        // 修改数据
        item.changeOverlap(overlap);
        return item;
    }

    public void changeIndex(final int newIndex) {
        this.changeBagType(bagType, newIndex);
    }

    public void changeBagType(Bag.BagType newBagType) {
        this.changeBagType(newBagType, bagIndex);
    }

    public void changeBagType(Bag.BagType newBagType, final int newIndex) {
        if (bagType == newBagType && newIndex == bagIndex) {
            return;
        }
        bagType = newBagType;
        bagIndex = newIndex;
        submitSave();
    }

    /**
     * 修改道具携带者
     *
     * @param newOwnerId 新携带者，可以为null
     */
    public void changeOwner(Integer newOwnerId) {
        if ((ownerId == null && newOwnerId == null) ||
                (ownerId != null && ownerId.equals(newOwnerId))) {
            return;
        }
        ownerId = newOwnerId;
        submitSave();
    }

    /**
     * @return 是否是装备
     */
    public boolean isEquipment() {
        return this.getTemplate().getIdentityType() == ItemDef.IdentityType.EQUIPMENT;
    }

    /**
     * 修改道具数量
     *
     * @param newOverlap 道具新数量
     */
    public void changeOverlap(final int newOverlap) {
        if (newOverlap == overlap) {
            return;
        }
        int oldOverlap = overlap;
        this.overlap = normalizeOverlap(newOverlap);

        if (overlap > 0) {
            // TODO 等有日志服务器
            submitSave();
        } else if (overlap == 0) {
            // TODO 等有日志服务器
            submitDelete();
        } else {
            throw new IllegalArgumentException("The overlap must not be <0");
        }
        // 触发物品数量变化事件
        IEvent event = new ItemCountChangeEvent(player.getOnline(), this, oldOverlap);
        eventDispatcher.fireEvent(event);
    }

    private int normalizeOverlap(int overlap) {
        int normalized;
        boolean ok = true;
        if (overlap < 0) {
            normalized = 0;
            ok = false;
        } else if (overlap > getMaxOverlap()) {
            normalized = getMaxOverlap();
            ok = false;
        } else {
            normalized = overlap;
        }
        if (!ok) {
            LOGGER.error("[normalizeOverlap] [非法的叠加数 id:{} overlap:{}]", id, overlap);
        }
        return normalized;
    }
}
